#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>

#include <time.h>
#include <stdlib.h>
#include <string.h>

void gendata(){  // 生成数据的功能
    int fd = open("b.txt", O_CREAT|O_WRONLY|O_TRUNC, 0644);
    srand(time(NULL));
    int data = 0;
    dup2(fd, 1);
    while(1){
        data = rand() % 1000 + 1;
        printf("%d\n", data);
        fflush(stdout); // 强制刷新
        sleep(1);
    }
}

int main(int argc, char const *argv[])
{
    // 获取IPC键
    key_t key = ftok("/", 150);
    int shmid = shmget(key, 20, IPC_CREAT|0644); // 获取共享内存或创建
    char *cmd = (char *)shmat(shmid, NULL, 0); // 映射共享内存，并获取它的内存地址
    bzero(cmd, 20); // 清空共享内存
    pid_t pid = 0;
main_label:
    pid = fork();
    if(pid == 0){
        gendata(); // 子进程核心功能: 生成数据
    }

wait_cmd:
    // 等待cmd指令
    while(strlen(cmd) == 0);

    if(strncmp(cmd, "regen", 5) == 0){
        // 重新生成
        kill(pid, SIGABRT); // 让子进程终止
        wait(NULL); // 等待子进程结束
        bzero(cmd, 20); // 清空共享内存，准备获取新的指令
        goto main_label;
    }else  if(strncmp(cmd, "stop", 4) == 0){
        kill(pid, SIGABRT); // 让子进程终止
        wait(NULL); // 等待子进程结束
        bzero(cmd, 20); // 清空共享内存，准备获取新的指令
    }else  if(strncmp(cmd, "count", 5) == 0){
        bzero(cmd, 20); // 清空共享内存，准备获取新的指令
        system("wc -l b.txt");
        goto wait_cmd;
    }else{
        printf("--%s invalid--\n", cmd);
        bzero(cmd, 20); // 清空共享内存，准备获取新的指令
        goto wait_cmd;
    }

    shmdt(cmd); // 取消共享内存映射
    printf("--over--\n");
    return 0;
}

